package com.macro.mall.config;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 健康检查配置类
 * 用于配置应用的健康检查端点和自定义健康指示器
 * 
 * @author mall
 * @since 1.0
 */
@Configuration
public class HealthCheckConfig {

    /**
     * 数据库连接健康检查指示器
     */
    @Bean
    public HealthIndicator databaseHealthIndicator(DataSource dataSource) {
        return () -> {
            try {
                JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
                // 执行简单查询验证数据库连接
                jdbcTemplate.queryForObject("SELECT 1", Integer.class);
                
                Map<String, Object> details = new HashMap<>();
                details.put("database", "MySQL");
                details.put("status", "连接正常");
                details.put("validationQuery", "SELECT 1");
                
                return Health.up()
                    .withDetails(details)
                    .build();
            } catch (Exception e) {
                Map<String, Object> details = new HashMap<>();
                details.put("database", "MySQL");
                details.put("status", "连接失败");
                details.put("error", e.getMessage());
                
                return Health.down()
                    .withDetails(details)
                    .build();
            }
        };
    }

    /**
     * Redis连接健康检查指示器
     */
    @Bean
    public HealthIndicator redisHealthIndicator(RedisTemplate<String, Object> redisTemplate) {
        return () -> {
            try {
                // 执行ping命令验证Redis连接
                String pong = redisTemplate.getConnectionFactory()
                    .getConnection()
                    .ping();
                
                Map<String, Object> details = new HashMap<>();
                details.put("redis", "Redis Cache");
                details.put("status", "连接正常");
                details.put("ping", pong);
                
                return Health.up()
                    .withDetails(details)
                    .build();
            } catch (Exception e) {
                Map<String, Object> details = new HashMap<>();
                details.put("redis", "Redis Cache");
                details.put("status", "连接失败");
                details.put("error", e.getMessage());
                
                return Health.down()
                    .withDetails(details)
                    .build();
            }
        };
    }

    /**
     * 应用自定义健康检查指示器
     */
    @Bean
    public HealthIndicator applicationHealthIndicator() {
        return () -> {
            try {
                // 检查应用关键组件状态
                Map<String, Object> details = new HashMap<>();
                details.put("application", "mall-admin");
                details.put("version", "1.0-SNAPSHOT");
                details.put("status", "运行正常");
                details.put("environment", System.getProperty("spring.profiles.active", "default"));
                details.put("jvm.memory.used", Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
                details.put("jvm.memory.max", Runtime.getRuntime().maxMemory());
                
                // 检查内存使用率
                long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
                long maxMemory = Runtime.getRuntime().maxMemory();
                double memoryUsage = (double) usedMemory / maxMemory;
                
                if (memoryUsage > 0.9) {
                    details.put("warning", "内存使用率过高: " + String.format("%.2f%%", memoryUsage * 100));
                    return Health.status(Status.UP)
                        .withDetails(details)
                        .build();
                }
                
                return Health.up()
                    .withDetails(details)
                    .build();
            } catch (Exception e) {
                Map<String, Object> details = new HashMap<>();
                details.put("application", "mall-admin");
                details.put("status", "异常");
                details.put("error", e.getMessage());
                
                return Health.down()
                    .withDetails(details)
                    .build();
            }
        };
    }
}